package com.zjnx.train.dao.impl;

import java.sql.SQLException;
import java.util.List;

import org.extremecomponents.table.limit.Limit;
import org.extremecomponents.table.limit.TableLimit;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Example.PropertySelector;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.zjnx.train.dao.UserDao;
import com.zjnx.train.entity.User;

/**
 * @author foo
 * @email foo@zjnx.com
 * @description:dao接口实现
 */
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

    public static final int DEFAULT_ROWS_DISPLAYED = 10;

    @Override
    public void save(User user) {
        getHibernateTemplate().save(user);
    }

    @Override
    public void update(User user) {
        getHibernateTemplate().update(user);
    }

    @Override
    public void delete(Long id) {
        User user = findByKey(id);
        if (user != null) {
            getHibernateTemplate().delete(user);
        }
    }

    @Override
    public User findByKey(Long id) {
        return getHibernateTemplate().get(User.class, id);
    }

    @Override
    public List<User> findAll() {
        return getHibernateTemplate().loadAll(User.class);
    }

    @Override
    public List<User> listAll(Limit limit, String queryString, Object... values) {
        TableLimit tableLimit = (TableLimit)limit;
        String countHQL = "select count(*) " + queryString;
        Integer totalRows = countAll(countHQL, values);
        tableLimit.setRowAttributes(totalRows, DEFAULT_ROWS_DISPLAYED);

        List<User> list = listAll(limit.getRowStart(), limit.getCurrentRowsDisplayed(), queryString, values);
        return list;
    }

    public Integer countAll(String hql, Object... values) {
        return ((Long)getHibernateTemplate().iterate(hql, values).next()).intValue();
    }

    /**
     * 使用hql 语句进行操作
     * 
     * @param offset
     *            開始取数据的下标
     * @param length
     *            读取数据记录数
     * @param hql
     *            HSQL 查询语句
     * @param values
     *            hql参数，有序
     * @return List 结果集
     */
    public List<User> listAll(final int offset, final int length, final String hql, Object... values) {
        return getHibernateTemplate().execute(new HibernateCallback<List<User>>() {
            @SuppressWarnings("unchecked")
            public List<User> doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(hql);
                if (values != null) {
                    for (int i = 0; i < values.length; i++) {
                        query.setParameter(i, values[i]);
                    }
                }
                query.setFirstResult(offset);
                query.setMaxResults(length);
                return query.list();
            }
        });
    }

    @Override
    public List<User> listAll(Limit limit, User user) {
        TableLimit tableLimit = (TableLimit)limit;

        Example example = Example.create(user);
        // NOT_BLANK NOT_NULL
        PropertySelector selector = new PropertySelector() {
            private static final long serialVersionUID = 1L;

            @Override
            public boolean include(Object value, String name, Type type) {
                if (StringType.class == type.getClass())
                    return value instanceof String && ((String)value).trim().length() > 0;
                else
                    return value != null;

            }
        };
        example.setPropertySelector(selector);
        Criteria criteria = this.getSessionFactory().getCurrentSession().createCriteria(User.class).add(example);
        Integer totalRows = countByCriteria(criteria);
        tableLimit.setRowAttributes(totalRows, DEFAULT_ROWS_DISPLAYED);

        criteria.setFirstResult(limit.getRowStart());
        criteria.setMaxResults(limit.getCurrentRowsDisplayed());
        @SuppressWarnings("unchecked")
        List<User> list = criteria.list();

        return list;
    }

    public int countByCriteria(Criteria criteria) {
        Projection projection = null;
        ResultTransformer resultTransformer = null;
        if (criteria instanceof CriteriaImpl) {
            projection = ((CriteriaImpl)criteria).getProjection();
            resultTransformer = ((CriteriaImpl)criteria).getResultTransformer();
        }
        // 统计查询
        Long count = (Long)criteria.setProjection(Projections.rowCount()).uniqueResult();
        // 统计后还原页查询
        criteria.setProjection(projection).setResultTransformer(resultTransformer);
        return count.intValue();
    }
}
